﻿using System.IO.Compression;

namespace SharpZip.Net
{

    public static class SharpZipFile
    {
        /// <summary>
        /// 提取压缩包到目录
        /// </summary>
        public static void ExtractToDirectory(string zipFile, string targetDir)
        {
            if (!File.Exists(zipFile))
            {
                throw new FileNotFoundException(zipFile);
            }

            if (!Directory.Exists(targetDir))
            {
                Directory.CreateDirectory(targetDir);
            }

            ZipFile.ExtractToDirectory(zipFile, targetDir);
        }

        /// <summary>
        /// 创建一个压缩包
        /// </summary>
        public static void CreateFromDirectory(string sourceDirectory, string targetZipFile, string[]? ignorePaths = null)
        {
            if (!Directory.Exists(sourceDirectory))
            {
                throw new DirectoryNotFoundException(sourceDirectory);
            }

            using (var memoryStream = CreateFromDirectory(sourceDirectory, ignorePaths))
            {
                using var fileStream = File.Open(targetZipFile, FileMode.CreateNew, FileAccess.Write, FileShare.Write);
                var bytes = memoryStream.ToArray();
                fileStream.Write(bytes);
            }
        }

        /// <summary>
        /// 指定目录创建一个 ZIP 存档
        /// </summary>
        public static MemoryStream CreateFromDirectory(string sourceDirectory, string[]? ignorePaths = null)
        {
            var files = GetDirectoryFileInfos(sourceDirectory, ignorePaths ?? []);
            var memoryStream = new MemoryStream();

            using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
            {
                foreach (var fileInfo in files)
                {
                    // 获取文件的相对路径（相对于源目录）
                    var entryName = Path.GetRelativePath(sourceDirectory, fileInfo.FullName);
                    Console.WriteLine(entryName);
                    // 创建一个 ZIP 条目（文件）
                    var zipArchiveEntry = zipArchive.CreateEntry(entryName);

                    // 打开 ZIP 条目以进行写入
                    using (Stream entryStream = zipArchiveEntry.Open())
                    {
                        using (FileStream sourceStream = fileInfo.OpenRead())
                        {
                            // 将源文件的内容复制到 ZIP 条目中
                            sourceStream.CopyTo(entryStream);
                        }
                    }
                }
            }

            return memoryStream;
        }

        /// <summary>
        /// 提取 ZIP 包到目录
        /// </summary>
        public static void ExtractToDirectory(string zipFile, string targetDir, AesEncryptorKey key)
        {
            if (!File.Exists(zipFile))
            {
                throw new FileNotFoundException(zipFile);
            }

            if (!Directory.Exists(targetDir))
            {
                Directory.CreateDirectory(targetDir);
            }

            var encryptedData = File.ReadAllBytes(zipFile);
            var data = AesEncryptor.Decrypt(encryptedData, key);

            ZipFile.ExtractToDirectory(new MemoryStream(data), targetDir);
        }

        /// <summary>
        /// 创建一个加密的 ZIP 包。
        /// </summary>
        public static void CreateFromDirectory(string sourceDirectory, string targetZipFile, AesEncryptorKey key, string[]? ignorePaths = null)
        {
            if (!Directory.Exists(sourceDirectory))
            {
                throw new DirectoryNotFoundException(sourceDirectory);
            }

            using (var memoryStream = CreateFromDirectory(sourceDirectory, key, ignorePaths))
            {
                using var fileStream = File.Open(targetZipFile, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Write);
                fileStream.Write(memoryStream.ToArray());
            }
        }

        /// <summary>
        /// 创建一个加密的 ZIP 包
        /// </summary>
        public static MemoryStream CreateFromDirectory(string sourceDirectory, AesEncryptorKey key, string[]? ignorePaths = null)
        {
            if (!Directory.Exists(sourceDirectory))
            {
                throw new DirectoryNotFoundException(sourceDirectory);
            }

            using (var memoryStream = CreateFromDirectory(sourceDirectory, ignorePaths))
            {
                var bytes = memoryStream.ToArray();
                var encryptedBytes = AesEncryptor.Encrypt(bytes, key);

                return new MemoryStream(encryptedBytes);
            }
        }

        /// <summary>
        /// 获取目录中的所有文件。
        /// </summary>
        private static List<FileInfo> GetDirectoryFileInfos(string directory, string[] ignorePaths)
        {
            List<FileInfo> fileInfos = new List<FileInfo>();
            DirectoryInfo currentDirectory = new DirectoryInfo(directory);

            Stack<DirectoryInfo> stack = new Stack<DirectoryInfo>();
            stack.Push(currentDirectory);

            while (stack.Any())
            {
                currentDirectory = stack.Pop();

                fileInfos.AddRange(currentDirectory.GetFiles());

                var childDirs = currentDirectory.GetDirectories();

                foreach (var childDir in childDirs)
                {
                    // 这里过滤掉不需要包含的目录
                    if (!ignorePaths.Contains(childDir.FullName))
                    {
                        stack.Push(childDir);
                    }
                }
            }

            return fileInfos;
        }
    }
}
